import { useFormChild, useQuasar } from '@teld/q-components';
import { cloneDeep, find, isNil, isEmpty } from 'lodash';
import useMappingProps from 't/common/hooks/useMappingProps';
import {
  commonProps,
  fixNameSpace,
  pickOwnForBasicComponent,
} from 't/common/utils';
import { defineComponent, inject, nextTick, ref, watch } from 'vue';
import Component from '../../basic/select';
import { FasApi } from './FasApi';
import styles from './index.module.scss';
import './index.scss';
export * from '../../basic/select';

export default defineComponent({
  name: fixNameSpace('QStateMachine'),
  props: {
    ...commonProps,
    ...Component.props,
    stateMachineId: {
      type: String,
      default() {
        return '';
      },
    },
    widgetObject: {
      type: Object,
      default() {
        return null;
      },
    },
    varDataRecord: {
      type: Object,
      default() {
        return null;
      },
    },
  },
  emits: ['changeVarData', 'selectChanged', 'dataChanged'],

  setup(props, { attrs, emit, expose, slots }) {
    const refComponent = ref();
    let $q = useQuasar();
    const [mappingProps, mappingExpose] = useMappingProps(props, {
      validate() {
        if (!stateMachineValidataState) {
          //校验不通过时Notify校验信息
          // $q.notify({
          //   closeBtn: true,
          //   type: 'negative',
          //   position: 'bottom-right',
          //   message: stateMachineValidataMsg,
          // });
          Funcs.Notify(
            '', //内容
            stateMachineValidataMsg, //标题
            'negative', //类型
            'bottom-right', //位置
          );
        }
        return stateMachineValidataState;
      },
      executeStateCheck(value) {
        if (window.Widget?.Root?.GetWidgetObject) {
          widgetObject = window.Widget.Root.GetWidgetObject();
        }
        if (value !== '' && value !== null && value !== undefined) {
          ruleCheck(value, false, value);
        } else {
          ruleCheck(currentState, false, currentState);
        }
      },
      resetStateMachine() {
        reset();
      },
      resetStateToEmptyString() {
        mappingProps.modelValue = '';
      },
      enableStateCheck(value) {
        needValidate.value = value;
      },
      initStateMachine() {
        nextTick(() => {
          widgetObject = window.Widget?.Root?.GetWidgetObject
            ? window.Widget.Root.GetWidgetObject()
            : mappingProps.widgetObject;
          varDataRecord = mappingProps.varDataRecord; //获取其他组件的实例和值
          initRecord = cloneDeep(varDataRecord); //备份数据，供修改了但没保存时，状态回退时回填
          initState = mappingProps.modelValue; //备份初始状态
          currentState = mappingProps.modelValue;
          if (mappingProps.stateMachineId) {
            initStateMachine();
          }
        });
      },
    });
    const { GetSMInfo, getDataByServiceUrl, getChangeDataByCdo } = FasApi();
    const executeScript = inject('executeScript'); //运行时传入的执行脚本的函数
    let currentState = null;
    let widgetObject = {};
    let varDataRecord = {}; //获取其他组件的实例和值
    let initRecord = {}; //备份数据，供修改了但没保存时，状态回退时回填
    let initState = null; //备份初始状态
    let stateMachineValidataState = true; //状态组件自身校验状态
    let stateMachineValidataMsg = ''; //状态组件校验状态提示信息
    const needValidate = ref(true);

    let widgetItemCacheBefroeChanged = {};
    let ruleData = [];
    let stateMachineMetaData = null;
    let initStateChangeFunction = null;

    mappingProps.options = [];

    expose(mappingExpose);

    useFormChild({
      validate: function () {
        if (!stateMachineValidataState) {
          Funcs.Notify(
            '', //内容
            stateMachineValidataMsg, //标题
            'negative', //类型
            'bottom-right', //位置
          );
        }
        return stateMachineValidataState;
      }, // 函数；可以是异步的；
      // 应该返回一个布尔值（或一个 resolve 布尔值的 Promise）
      resetValidation: function () {
        stateMachineValidataState = true;
        stateMachineValidataMsg = '';
      }, // 可选的函数，可重置验证
      requiresQForm: false, // 如果没有找到父级 QForm，它是否应该报错？
    });

    const initStateMachine = async () => {
      console.log(widgetObject, '组件实例');
      //获取状态机的元数据,里面有关于状态机的所有信息
      stateMachineMetaData = await GetSMInfo(mappingProps.stateMachineId);
      if (isNil(mappingProps.modelValue) || mappingProps.modelValue === '') {
        let eventItem = find(stateMachineMetaData.Content.Transitions, {
          FromStateID: '',
        });
        if (eventItem) {
          makeOptions([eventItem.To]);
          initStateChangeFunction = [eventItem.To.Rules, false];
        }
      } else {
        //获取状态机的状态规则
        getDataByServiceUrl('FASR-GetTransitionStates', {
          StateMachineID: mappingProps.stateMachineId, //状态机ID
          stateKey: mappingProps.modelValue, //当前状态值
          record:
            Object.keys(varDataRecord).length === 0
              ? null
              : JSON.stringify(varDataRecord), //绑定对象的所有数据，可以理解为当前表单绑定对象的内容
        }).then(data => {
          if (data.state == 1) {
            ruleData = data.data;
            makeOptions(ruleData);
            ruleCheck(mappingProps.modelValue);
          }
        });
      }
    };
    function reset() {
      stateMachineValidataState = true;
      stateMachineValidataMsg = '';
      widgetItemCacheBefroeChanged = {};
      ruleData = [];
      stateMachineMetaData = null;
    }
    //生成下拉框选项
    function makeOptions(data) {
      let options = [];
      data.forEach(item => {
        options.push({
          id: item.ID,
          label: item.Name,
          value: item.Key,
          sort: item.Sort,
        });
      });
      options.sort((a, b) => a.sort - b.sort);
      mappingProps.options = options;
    }
    function resetFieldsState(valueDetail, oldValueRule, repeatCheck) {
      //先恢复初始值再修改
      ['ID_Required', 'ID_ReadOnly', 'ID_Frozen'].forEach(type => {
        let requiredRules = valueDetail.filter(item => item.Key === type);
        let oldRequiredRules = oldValueRule.filter(item => item.Key === type);
        const requiredRuleFieldsArray = requiredRules.reduce(
          (accumulator, currentObject) => {
            // accumulator 是累加器，它在每次迭代中累积结果。
            // currentObject 是当前正在处理的对象
            // reduce 方法从数组的第一个元素开始，将每个元素（及其累加器的当前值）传递给回调函数，最终返回合并后的数组。初始值是一个空数组 []，在 reduce 的第二个参数中指定
            let arrayOfObjects = [...accumulator, ...currentObject.RuleFields];
            const uniqueObjects = arrayOfObjects.reduce((acc, obj) => {
              if (!acc.some(item => item.ColumnName === obj.ColumnName)) {
                acc.push(obj);
              }
              return acc;
            }, []);
            return uniqueObjects;
          },
          [],
        );
        const oldRequiredRuleFieldsArray = oldRequiredRules.reduce(
          (accumulator, currentObject) => {
            let arrayOfObjects = [...accumulator, ...currentObject.RuleFields];
            const uniqueObjects = arrayOfObjects.reduce((acc, obj) => {
              if (!acc.some(item => item.ColumnName === obj.ColumnName)) {
                acc.push(obj);
              }
              return acc;
            }, []);
            return uniqueObjects;
          },
          [],
        );
        // 比较新老规则 哪些规则不再使用了
        const nonExistingObjects = oldRequiredRuleFieldsArray.filter(obj1 => {
          return !requiredRuleFieldsArray.some(
            obj2 => obj2.ColumnName === obj1.ColumnName,
          );
        });
        if (nonExistingObjects && nonExistingObjects.length > 0) {
          nonExistingObjects.forEach(item => {
            let widgetItem = widgetObject[item.ColumnName];
            if (widgetItem) {
              switch (type) {
                case 'ID_Required':
                  widgetItem.required = false;
                  widgetItem.rules = [];
                  nextTick(() => {
                    try {
                      let result = widgetItem.resetValidation(); //主动触发校验
                    } catch (error) {
                      console.log(error);
                    }
                  });
                  break;
                case 'ID_ReadOnly':
                  widgetItem.readonly = false;
                  break;
                case 'ID_Frozen':
                  widgetItem.disable = false;
                  break;
              }
            }
          });
        }
        if (repeatCheck) {
          requiredRuleFieldsArray.forEach(item => {
            let widgetItem = widgetObject[item.ColumnName];
            if (widgetItem) {
              switch (type) {
                case 'ID_Required':
                  widgetItem.required = false;
                  widgetItem.rules = [];
                  nextTick(() => {
                    try {
                      let result = widgetItem.resetValidation(); //主动触发校验
                    } catch (error) {
                      console.log(error);
                    }
                  });
                  break;
                case 'ID_ReadOnly':
                  widgetItem.readonly = false;
                  break;
                case 'ID_Frozen':
                  widgetItem.disable = false;
                  break;
              }
            }
          });
        }
      });
    }
    //规则校验
    function ruleCheck(value, isBack, oldVal) {
      stateMachineValidataState = true;
      stateMachineValidataMsg = '';
      //1.根据当前状态值找到相关规则
      let valueDetail = ruleData.find(item => item.Key == value);
      let valueRule = [];
      if (valueDetail) {
        valueRule = valueDetail.Rules;
        //修改前恢复初始状态
        let oldValueDetail = ruleData.find(item => item.Key == oldVal);
        if (oldValueDetail) {
          resetFieldsState(valueRule, oldValueDetail.Rules, value == oldVal);
        }
      } else {
        if (initStateChangeFunction) {
          ruleCheckMethod(
            initStateChangeFunction[0],
            initStateChangeFunction[1],
          );
        }
      }
      //2.遍历规则，检查指定字段对应的组件是否满足规则
      ruleCheckMethod(valueRule, isBack, value == oldVal);
    }
    function ruleCheckMethod(valueRule, isBack, isRepeat) {
      valueRule.forEach(async item => {
        //是前置条件，先执行前置条件的表达式，再遍历需要执行该规则的字段，并找到对应的组件，执行校验
        if (item.HasCondition) {
          let conditionExpressionResult = await execExpression(
            item.ConditionExpression,
          );
          if (!conditionExpressionResult) {
            return;
          }
        }
        if (item.RuleFields && item.RuleFields.length > 0) {
          item.RuleFields.forEach(field => {
            let fieldComponent = widgetObject.hasOwnProperty(field.ColumnName)
              ? widgetObject[field.ColumnName]
              : null;
            executeValidata(
              field.ColumnName, //字段名称
              fieldComponent, //字段对应的组件实例
              item.Key, //规则的key
              isBack, //是否是回滚数据
              isRepeat,
            );
          });
        }
        if (
          item.RuleFields &&
          item.RuleFields.length == 0 &&
          item.Key == 'FAS.Expression.Rule'
        ) {
          //此类规则当做表达式执行，并根据返回值修改状态组件本身校验状态
          processRuleContents(item);
        }
      });
    }
    async function processRuleContents(item) {
      let resultCount = 0;
      // 使用 Promise.all 来并行处理 RuleContents 中的每个 contents
      try {
        const promises = item.RuleContents.map(async contents => {
          if (contents.RuleInfo) {
            const result = await execExpression(contents.RuleInfo);
            // 如果有返回值，则修改状态组件本身校验状态
            if (typeof result === 'boolean') {
              return !result;
            }
          }
        });

        const results = await Promise.all(promises);

        resultCount = results.filter(result => result).length;

        // 根据 resultCount 更新状态
        updateStateMachineState(
          resultCount === 0,
          resultCount === 0 ? '' : item.Description,
        );
      } catch (error) {
        console.error('Error processing RuleContents:', error);
        // 在这里处理任何 Promise.all 中的异常
      }
    }
    function updateStateMachineState(isValid, msg) {
      stateMachineValidataState = isValid;
      stateMachineValidataMsg = msg;
    }
    //执行规则
    function executeValidata(key, widgetItem, rule, isBack, isRepeat) {
      console.log(key, widgetItem, '执行规则');
      if (
        widgetItem &&
        Object.prototype.toString.call(widgetItem) === '[object Object]'
      ) {
        switch (rule) {
          case 'ID_Required':
            //备份修改前的数据
            if (!isRepeat) {
              if (!isBack) {
                if (widgetItemCacheBefroeChanged.hasOwnProperty(key)) {
                  widgetItemCacheBefroeChanged[key].required =
                    widgetItem.required;
                  widgetItemCacheBefroeChanged[key].rules = widgetItem.rules;
                } else {
                  widgetItemCacheBefroeChanged[key] = {
                    required: widgetItem.required,
                    rules: widgetItem.rules,
                  };
                }
              }
            }
            widgetItem.required = true; //设置必填状态
            widgetItem.rules = [
              (val => !!val || val === 0 || val === false) ||
                $q.lang.editTable?.requiredMsg,
            ]; //设置规则
            nextTick(() => {
              try {
                if (needValidate) {
                  let result = widgetItem.validate(); //主动触发校验
                }

              } catch (error) {
                console.log(error, key);
              }
            });
            break;
          case 'ID_ReadOnly':
            //备份修改前的数据
            if (!isRepeat) {
              if (!isBack) {
                if (widgetItemCacheBefroeChanged.hasOwnProperty(key)) {
                  widgetItemCacheBefroeChanged[key].readonly =
                    widgetItem.readonly;
                } else {
                  widgetItemCacheBefroeChanged[key] = {
                    readonly: widgetItem.readonly,
                  };
                }
              }
            }
            widgetItem.readonly = true;
            try {
              widgetItem.resetValidation();
            } catch (error) {
              console.log(error);
            }
            break;
          case 'ID_Frozen':
            //备份修改前的数据
            if (!isRepeat) {
              if (!isBack) {
                if (widgetItemCacheBefroeChanged.hasOwnProperty(key)) {
                  widgetItemCacheBefroeChanged[key].disable =
                    widgetItem.disable;
                } else {
                  widgetItemCacheBefroeChanged[key] = {
                    disable: widgetItem.disable,
                  };
                }
              }
            }
            widgetItem.disable = true;
            break;
        }
      }
    }
    //执行表达式
    async function execExpression(expression) {
      // return Funcs.Eval(expression);
      let exp = expression;
      if (executeScript) {
        // if (!expression.startsWith('return')) {
        //   exp = `return ${expression}`;
        // }
        const response = await executeScript(exp);
        return response;
      }
    }
    //值发生变化时调用接口执行状态机的事件，获取变化后数据
    function changeStateFunction(value, previousValue) {
      if (!stateMachineMetaData) {
        return;
      }
      let fromStateID = find(stateMachineMetaData.Content.States, {
        Key: previousValue,
      });
      let toStateID = find(stateMachineMetaData.Content.States, {
        Key: value,
      });
      let eventItem = find(stateMachineMetaData.Content.Transitions, {
        FromStateID: fromStateID ? fromStateID.ID : '',
        ToStateID: toStateID ? toStateID.ID : '',
      });
      let record = cloneDeep(varDataRecord);
      try {
        record[stateMachineMetaData.Content.CDOColKey] =
          initRecord[stateMachineMetaData.Content.CDOColKey];
      } catch (error) {
        console.log(error);
      }
      if (!eventItem) {
        //没找到切换事件，比如说卡片界面上一页下一页，此时赋值不属于状态机切换事件
        return;
      }
      getChangeDataByCdo(
        stateMachineMetaData.Content.CDOMetadataID, //状态机绑定的CDO元数据id
        stateMachineMetaData.Content.CDOColKey, //状态机绑定的字段
        eventItem?.Event.Key, //事件的key值
        record, //表单对象，重点是里面绑定的状态属性，需要是变化前的值fromState，会根据这个源状态找事件
      ).then(data => {
        //拿到的数据重新赋值
        if (data.state == '1') {
          let returnValue = data.data.Record;
          //调用外部方法修改localvars的属性值
          Object.entries(returnValue).forEach(([key, val]) => {
            emit('changeVarData', key, val);
          });
          emit('dataChanged', returnValue);
        }
      });
    }
    function resetInitData(justState) {
      //设置为之前备份的初始值
      if (!justState) {
        Object.entries(initRecord).forEach(([key, val]) => {
          emit('changeVarData', key, val);
        });
      }
      //重置规则
      Object.entries(widgetItemCacheBefroeChanged).forEach(
        ([key, objvalueCache]) => {
          if (widgetObject.hasOwnProperty(key)) {
            if (objvalueCache.hasOwnProperty('required')) {
              widgetObject[key].required = objvalueCache.required;
              widgetObject[key].rules = objvalueCache.rules;
              try {
                widgetObject[key].resetValidation();
              } catch (error) {}
            }
            if (objvalueCache.hasOwnProperty('readonly')) {
              widgetObject[key].readonly = objvalueCache.readonly;
            }
          }
        },
      );
    }

    watch(
      () => {
        return [mappingProps.modelValue, mappingProps.stateMachineId];
      },
      (newVal, oldVal) => {
        if (newVal[0]?.toString() != oldVal[0]?.toString()) {
          if (
            // mappingProps.disable ||
            // mappingProps.readonly ||
            oldVal[0] === '' ||
            newVal[0] === ''
          ) {
            resetInitData(true);
            return;
          }
          currentState = newVal[0];
          //下拉值切换时根据当前值，从状态机数据详情中找到对应规则进行校验，看是否符合
          if (newVal[0]?.toString() == initState?.toString()) {
            //改回初始状态时，回填初始状态的数据，回复初始规则
            resetInitData();
          } else {
            changeStateFunction(newVal[0], oldVal[0]);
          }
          ruleCheck(
            newVal[0],
            newVal[0]?.toString() == initState?.toString(),
            oldVal[0],
          ); //回填时标记一下，特殊处理检查方法，避免检查时重复缓存修改前的数据
        }
        if (newVal[1] != oldVal[1]) {
          if (mappingProps.stateMachineId) {
            initStateMachine();
          } else {
            reset();
          }
        }
      },
    );

    return () => {
      return (
        <Component
          ref={refComponent}
          {...attrs}
          {...pickOwnForBasicComponent(mappingProps, Component.props, attrs)}
          class={['t-state-machine', styles.module, 'no-outline']}
          v-show={mappingProps.visible}
          use-input={attrs.placeholder ? true : false}
          tabindex='-1'
          onChange={value => {
            emit('selectChanged', value);
          }}
          // v-slots={{ ...slots }}
        >
          {slots}
        </Component>
      );
    };
  },
});
